package com.rockcent.wechat.controller;

import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.WithdrawCrowd;
import com.rockcent.mall.lib.domain.enumclass.WithdrawStatus;
import com.rockcent.mall.lib.domain.enumclass.CustomerCouponWalletStatus;
import com.rockcent.mall.lib.dto.CustomerBankDto;
import com.rockcent.mall.lib.dto.CustomerDto;
import com.rockcent.mall.lib.dto.CustomerFundDto;
import com.rockcent.mall.lib.dto.CustomerFundFlowDto;
import com.rockcent.mall.lib.dto.CustomerWithdrawDto;
import com.rockcent.mall.lib.repository.*;
import com.rockcent.service.IntegrationCashCouponWalletSrv;
import com.rockcent.wechat.Routes;
import com.rockcent.wechat.helper.CustomerHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.apache.commons.beanutils.BeanUtilsBean2;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Created by zhangjh on 2016/9/30.
 */
@RestController
@RequestMapping(value = Routes.API_PREFIX)
public class CustomerWalletController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(CustomerWalletController.class);

    @Autowired
    private CustomerFundRepository customerFundRepository;

    @Autowired
    private BankRepository bankRepository;
    @Autowired
    private CustomerBankRepository customerBankRepository;
    @Autowired
    private CustomerHelper customerHelper;
    @Autowired
    private CustomerFundFlowRepository customerFundFlowRepository;
    @Autowired
    private CustomerWithdrawRepository customerWithdrawRepository;
    @Autowired
    private WithdrawEventRepository withdrawEventRepository;
    private MallOrderRepository mallOrderRepository;
    @Autowired
    private CustomerCouponWalletRepository customerCouponWalletRepository;

    @Autowired
    private IntegrationCashCouponWalletSrv integrationCashCouponWalletSrv;
    /**
     * @api {get} /api/v2/customer/wallet/show 用户钱包信息
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     *
     * @apiSuccess {Long} id 钱包ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 版本
     * @apiSuccess {BigDecimal} totalAmount 总金额
     * @apiSuccess {BigDecimal} frozen 冻结金额
     * @apiSuccess {BigDecimal} income 累计收入
     * @apiSuccess {BigDecimal} expend 累计支出
     * @apiSuccess {BigDecimal} availableAmount 可用金额
     *
     * @apiSuccessExample {json} Success-Response:
     *  {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": {
     *              "id": 489,
     *              "dateCreated": "2016-09-30 10:58:20",
     *              "lastUpdated": "2016-09-30 10:58:20",
     *              "version": 0,
     *              "totalAmount": 0,
     *              "frozen": 0,
     *              "income": 0,
     *              "expend": 0,
     *              "availableAmount" : 0,
     *              "customerId": 512
     *          }
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_WALLET_SHOW, method = RequestMethod.GET)
    public JsonResult show(HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        //log.info("======================>customerDto-->"+customerDto);
        RestDoing doing = jr -> {
            CustomerFund customerFund = customerFundRepository.findByCustomerIdAndIsDelete(customerDto.getId(), Whether.NO);
            CustomerFundDto dto = new CustomerFundDto();
            BeanUtilsBean2.getInstance().copyProperties(dto,customerFund);
            Long toUse = customerCouponWalletRepository.countByCustomerIdAndStatusAndIsDelete(customerDto.getId(), CustomerCouponWalletStatus.TO_USE,Whether.NO);
            Long userId = customerDto.getId();
            Long unUsedTotal = integrationCashCouponWalletSrv.queryCashWalletCount(0l, userId);
//            log.info("======================>toUse:"+toUse);
//            log.info("======================>unUsedTotal:"+unUsedTotal);
            dto.setToUseCountCoupon(toUse);
            dto.setToUseCountCash(unUsedTotal);
            jr.setData(dto);
        };
        return doing.go(request, log);
    }

    /**
     *
     * @api {get} /api/v2/customer/bank/list_binding  查询用户绑定的银行卡列表
     * @apiGroup customer
     * @apiVersion 1.0.0
     * @apiParam {String} userToken 用户Token
     *
     * @apiSuccess {Long} id 银行卡ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 版本
     * @apiSuccess {String} bankCard 银行卡号
     * @apiSuccess {Long} bankTypeId 银行卡类型
     * @apiSuccess {String} cardHolder 持卡人
     * @apiSuccess {Long} customerId 客户ID
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *   "code": "1",
     *   "desc": "成功",
     *   "data": [
     *      {
     *          "id": 1,
     *          "dateCreated": "2016-09-23 13:47:48",
     *          "lastUpdated": "2016-09-27 10:26:44",
     *          "version": 2,
     *          "bankCard": "1111111111",
     *          "bankTypeId": 1,
     *          "cardHolder": "555",
     *          "customerId": 1
     *      }
     *   ]
     *   }
     */
    @RequestMapping(value = Routes.CUSTOMER_BANK_LIST_BINDING, method = RequestMethod.GET)
    public JsonResult listBinding(HttpServletRequest request) {
        RestDoing doing = jr -> {
            CustomerDto customerDto = customerHelper.getSession(request);
            List<CustomerBank> customerBankList = customerBankRepository.findByCustomerId(customerDto.getId());
            customerBankList.stream().map(customerBank -> {
                Bank bank = bankRepository.findOne(customerBank.getBankTypeId());
                CustomerBankDto customerBankDto = new CustomerBankDto();
                customerBankDto.setId(customerBank.getId());
                customerBankDto.setCode(bank.getCode());
                customerBankDto.setAccountNo(hideCard(customerBank.getBankCard()));
                customerBankDto.setBankCardHolder(customerBank.getCardHolder());
                return customerBank;
            });
            jr.setData(customerBankList);
        };
        return doing.go(request, log);
    }

    private String hideCard(String bankCard) {
        String last4 = bankCard.substring(bankCard.length() - 4);
        return "**** **** **** " + last4;

    }

    /**
     *
     * @api {post} /api/v2/customer/bank/binding 用户绑定银行卡
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     * @apiParam { Long } bankCard 银行卡号
     * @apiParam { Long } bankTypeId 银行类型代码
     * @apiParam { String } cardHolder 持卡人
     * @apiParam {Long} phone 用户手机号
     *
     * @apiSuccess {Long} data 成功返回true
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *   "code": "1",
     *   "desc": "成功",
     *   "data": true
     *   }
     */
    @RequestMapping(value = Routes.CUSTOMER_BANK_BINDING, method = RequestMethod.POST)
    public JsonResult bindingBank(CustomerBank customerBank, HttpServletRequest request) {
        RestDoing doing = jr -> {
            if (null == customerBank.getBankCard()) {
                jr.remind("银行卡号不能为空",log);
                return;
            }
            if (null == customerBank.getBankTypeId()) {
                jr.remind("银行卡类型不能为空",log);
                return;
            }
            if (null == customerBank.getCardHolder()) {
                jr.remind("持卡人不能为空",log);
                return;
            }
            if (null == customerBank.getPhone() || !Pattern.compile("^1(3|4|5|7|8)\\d{9}$").matcher(customerBank.getPhone().toString()).matches()) {
                jr.errorParam("请正确输入手机号码",log);
                return;
            }
            Bank bank = bankRepository.findOne(customerBank.getBankTypeId());
            if (null == bank) {
                jr.remind("不支持的银行类型",log);
                return;
            }
            //通过userToken获取用户信息
            CustomerDto customerDto = customerHelper.getSession(request);
            CustomerBank customerBank2 = customerBankRepository.findByCustomerIdAndBankCard(customerDto.getId(), customerBank.getBankCard());

            if (customerBank2 != null) {
                jr.remind("已经绑定过此银行卡",log);
                return;
            }


            customerBank.setCustomerId(customerDto.getId());
            CustomerBank cb = customerBankRepository.save(customerBank);
            if (null == cb) {
                jr.errorParam("操作不成功",log);
                return;
            }

            jr.setData(true);

        };
        return doing.go(request, log);
    }

    /**
     *
     * @api {post} /api/v2/customer/bank/update 用户修改银行卡
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {String} userToken 用户Token
     * @apiParam {Long} id 银行卡ID
     * @apiParam { Long } [bankCard] 银行卡号
     * @apiParam { Long } [bankTypeId] 银行类型代码
     * @apiParam { String } [cardHolder] 持卡人
     * @apiParam {Long} [phone] 用户手机号
     *
     * @apiSuccess {Long} data 成功返回true
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *   "code": "1",
     *   "desc": "成功",
     *   "data": true
     *   }
     */
    @RequestMapping(value = Routes.CUSTOMER_BANK_UPDATE, method = RequestMethod.POST)
    public JsonResult updateBank(CustomerBank customerBank, HttpServletRequest request) {
        RestDoing doing = jr -> {
            //信息不能为null
            if (customerBank.getBankCard()==null||customerBank.getBankTypeId()==null||customerBank.getCardHolder()==null||customerBank.getPhone()==null){
                jr.remind("请完善绑定信息",log);
                return;
            }
            CustomerDto customerDto = customerHelper.getSession(request);
            //验证手机规则
            if (null != customerBank.getPhone() && !Pattern.compile("^1(3|4|5|7|8)\\d{9}$").matcher(customerBank.getPhone().toString()).matches()) {
                jr.errorParam("请正确输入手机号码",log);
                return;
            }
            //检查是否已经绑定该银行卡
            CustomerBank customerBank2 = customerBankRepository.findOne(customerBank.getId());
            if (null == customerBank2 || !customerBank2.getCustomerId().equals(customerDto.getId())) {
                jr.remind("查无此记录",log);
                return;
            }
            //卡类型验证
            if (null != customerBank.getBankTypeId()) {
                Bank bank = bankRepository.findOne(customerBank.getBankTypeId());
                if (null == bank) {
                    jr.remind("不支持的银行类型",log);
                    return;
                }
                customerBank2.setBankTypeId(customerBank.getBankTypeId());
            }
            //设置绑定信息
            customerBank2.setBankCard(customerBank.getBankCard());
            customerBank2.setCardHolder(customerBank.getCardHolder());
            customerBank2.setPhone(customerBank.getPhone());
            if (null == customerBankRepository.save(customerBank2)) {
                jr.errorParam("操作不成功",log);
                return;
            }
            jr.setData(true);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/customer/bank/remove_binding 解除绑定银行卡
     * @apiGroup customer
     * @apiParam { String } userToken 用户Token
     * @apiParam { Long } bankCard 银行卡号
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": true
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_BANK_REMOVE_BINDING, method = RequestMethod.POST)
    public JsonResult removeBinding(Long customerId, String bankCard, HttpServletRequest request) {
        RestDoing doing = jr -> {
            if (null == bankCard) {
                jr.remind("银行卡号不能为空",log);
            }
            CustomerDto customerDto = customerHelper.getSession(request);
            CustomerBank customerBank = customerBankRepository.findByCustomerIdAndBankCard(customerDto.getId(), bankCard);
            if (customerBank == null) {
                jr.remind("此银行卡已经解除绑定",log);
                return;
            }
            customerBankRepository.delete(customerBank);
            jr.setData(true);
        };
        return doing.go(request, log);
    }


    /**
     *
     * @api {get} /api/v2/customer/bank/support_bank 支持银行类型
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiSuccess {Long} id 银行类型ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 版本
     * @apiSuccess {String} code 银行简称
     * @apiSuccess {String} name 银行名称
     * @apiSuccess {Integer} seqNo 序号
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": [
     *              {
     *                  "id": 1,
     *                  "dateCreated": "2016-09-23 16:43:15",
     *                  "lastUpdated": "2016-09-23 16:43:16",
     *                  "version": 0,
     *                  "code": "CCB",
     *                  "name": "中国建设银行",
     *                  "seqNo": 1
     *              },
     *               ...
     *  ]
     * }
     */
    @RequestMapping(value = Routes.CUSTOMER_BANK_SUPPORT_BANK, method = RequestMethod.GET)
    public JsonResult supportBank(HttpServletRequest request) {
        RestDoing doing = jr -> {
            List<Bank> bankList = bankRepository.findAll();

            jr.setData(bankList);
        };
        return doing.go(request, log);
    }
    /**
     *
     * @api {get} /api/v2/customer/wallet/detail 用户收支明细
     * @apiGroup customer
     * @apiVersion 1.0.0
     *
     * @apiParam {Integer} pageNo 页码
     * @apiParam {Integer} pageSize 每页记录数
     *
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {String} operationAmount 当前操作金额
     * @apiSuccess {String} transactionFlow 收支类型 INCOME 收入 ，EXPEND 支出
     * @apiSuccess {BigDecimal} transactionType 交易类型 ORDER_RECHARGE("充值"),SHOP("购物"),SHARE_FEE("分享返利收入")
     * @apiSuccess {BigDecimal} mallOrderNum 订单号
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": [
     *              {
     *                  "dateCreated": "2016-11-21 16:21:56",
     *                  "operationAmount": 0.01,
     *                  "transactionFlow": "INCOME",
     *                  "transactionType": "ORDER_RECHARGE",
     *                  "mallOrderNum": "201611211621212535254436"
     *              },
     *              ...
     *          ]
     *  }
     */
    @RequestMapping(value = Routes.CUSTOMER_WALLET_DETAIL, method = RequestMethod.GET)
    public JsonResult showDetail(Integer pageNo , Integer pageSize ,HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (pageNo == null || pageSize == null){
                jr.remind("请输入分页条件",log);
                return;
            }
            PageResult<CustomerFundFlowDto> customerFundFlowPage = customerFundFlowRepository.findCustomerIdPage(customerDto.getId(),customerDto.getMallId(),Whether.NO,this.getPage(pageNo,pageSize));
            List<CustomerFundFlowDto> customerFundFlowDtos = customerFundFlowPage.data;
            if (null != customerFundFlowPage && customerFundFlowDtos != null && !customerFundFlowDtos.isEmpty()) {
                customerFundFlowDtos =  customerFundFlowDtos.stream().map(customerFundFlowDto -> {
                    customerFundFlowDto.setOperationAmountShow(customerFundFlowDto.getOperationAmount().setScale(2,BigDecimal.ROUND_HALF_UP).toString());
                    return customerFundFlowDto;
                }).collect(Collectors.toList());
            }
            customerFundFlowPage.setData(customerFundFlowDtos);
            jr.setData(customerFundFlowPage);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/customer/apply/withdraw 提现
     * @apiGroup customer
     * @apiParam {String} userToken 用户Token
     *
     * @apiParam {String} bankNo 银行卡号
     * @apiParam {BigDecimal} amount 提现金额
     * @apiParam {String} bankName 银行名称
     *
     * @apiSuccessExample { json } Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  }
     */
    @Transactional
    @RequestMapping(value = Routes.CUSTOMER_APPLY_WITHDRAW, method = RequestMethod.POST)
    public JsonResult applyWithdraw(HttpServletRequest request, @RequestBody CustomerWithdrawDto dto) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getAmount() == null || dto.getAmount() == BigDecimal.ZERO) {
                jsonResult.remind("提现金额 不能为空",log);
                return;
            }

            if (StringUtils.isBlank(dto.getBankNo())) {
                jsonResult.remind("银行卡号 不能为空",log);
                return;
            }

            if (StringUtils.isBlank(dto.getBankName())) {
                jsonResult.remind("银行名称 不能为空",log);
                return;
            }

            CustomerBank customerBank = customerBankRepository.findByCustomerIdAndBankCard(customerDto.getId(), dto.getBankNo());
            if (customerBank == null) {
                jsonResult.remind("银行卡号 不存在",log);
                return;
            }
            CustomerFund customerFund = customerFundRepository.findByCustomerId(customerDto.getId());
            if (customerFund == null) {
                jsonResult.remind("登录帐号异常,请联系客户人员",log);
                return;
            }

            if (dto.getAmount().compareTo(customerFund.getAvailableAmount()) > 0) {
                jsonResult.remind("可用余额不足",log);
                return;
            }

            //可用金额减少,冻结资金增加
            customerFund.setAvailableAmount(customerFund.getAvailableAmount().subtract(dto.getAmount()));
            customerFund.setFrozen(customerFund.getFrozen().add(dto.getAmount()));
            customerFundRepository.save(customerFund);

            //申请提现
            CustomerWithdraw customerWithdraw = new CustomerWithdraw();
            customerWithdraw.setMallId(customerDto.getMallId());
            customerWithdraw.setCustomerId(customerDto.getId());
            customerWithdraw.setBankAccountName(customerBank.getCardHolder());
            customerWithdraw.setBankNo(dto.getBankNo());
            customerWithdraw.setAmount(dto.getAmount());
            customerWithdraw.setBankName(dto.getBankName());
            customerWithdraw.setStatus(WithdrawStatus.WAIT_AUDIT);
            customerWithdraw.setBankInfo(dto.getBankName() + "+" + customerBank.getCardHolder() + "+" + dto.getBankNo());
            customerWithdraw = customerWithdrawRepository.save(customerWithdraw);

            //提现事件记录
            WithdrawEvent withdrawEvent = new WithdrawEvent();
            withdrawEvent.setStatus(WithdrawStatus.WAIT_AUDIT);
            withdrawEvent.setMallId(customerDto.getMallId());
            withdrawEvent.setApplyWithdrawId(customerWithdraw.getId());
            withdrawEvent.setOperatorId(customerDto.getId());
            withdrawEvent.setProposerId(customerDto.getId());
            withdrawEvent.setWithdrawCrowd(WithdrawCrowd.CUSTOMER);
            withdrawEventRepository.save(withdrawEvent);
        };
        return doing.go(request, log);
    }
}
